#include <Winsock2.h>
#include <math.h>
#include "Algorithms.h"
#include "Types.h"
#include "Hw4RandomNumbers.h"
#include "VectorOperations.h"
#include <stdio.h>

#ifndef M_PI
	#define M_PI 3.14159265358979323846
#endif


// Algorithm 0
BOOL EventOccured(double ProbabilityOfEventToOccur)
{
	return (RandomUniform() < ProbabilityOfEventToOccur);
}

// Algorithm 1
TVelocity EvaluateVelocity(TVelocity CurrentVelocity, double VelocityStdDiv)
{
	TVelocity NewVelocity ;
	double VelocityErrorX, VelocityErrorY;
	VelocityErrorX = VelocityStdDiv*RandomGaussian();
	VelocityErrorY = VelocityStdDiv*RandomGaussian();
	NewVelocity.x = (1+VelocityErrorX)*CurrentVelocity.x;
	NewVelocity.y = (1+VelocityErrorY)*CurrentVelocity.y;
	return NewVelocity;
}

// Algorithm 2
TPosition EvaluatePosition(TPosition LastPosition, TVelocity NewVelovity, double PositionStdDiv)
{
	TPosition PositionError, NewPosition;
	PositionError.x = PositionStdDiv*RandomGaussian();
	PositionError.y = PositionStdDiv*RandomGaussian();
	NewPosition = AddVectors(PositionError, LastPosition);
	NewPosition = AddVectors(NewPosition, NewVelovity);
	return NewPosition;
}

// Algorithm 3


// Algorithm 4
void VerifyInterception(
	TPosition RocketPosition, 
	TPosition InterceptorPosition, 
	double MaxDistanceForInterception, 
	double SuccessProbability, 
	BOOL *InterceptDestroyedOutputPtr, BOOL *RocketDestroyedOutputPtr)
{
	double Distance = CalculateDistance(RocketPosition, InterceptorPosition);
	printf("Calculated distance between rocket and interceptor: %.3g\n", Distance);
	if (Distance < MaxDistanceForInterception)
	{
		BOOL Success = EventOccured(SuccessProbability);
		if (Success == TRUE)
		{
			*RocketDestroyedOutputPtr = TRUE;
			*InterceptDestroyedOutputPtr = TRUE;
		}
		else
		{
			*InterceptDestroyedOutputPtr = TRUE;
			*RocketDestroyedOutputPtr = FALSE;
		}
	}
	else
	{
		*InterceptDestroyedOutputPtr = FALSE;
		*RocketDestroyedOutputPtr = FALSE;
	}
}


// Algorithm 5
TVelocity DetermineInterceptorDirection(
	TPosition RocketPosition, 
	TVelocity RocketVelocity, 
	TPosition InterceptorPosition,
	double InterceptorSpeed
	)
{
	TPosition NextRocketPosition;
	TVector DifferenceVector;
	double DifferenceVectorSize;
	TVelocity NewVelocity;

	NextRocketPosition = AddVectors(RocketPosition, RocketVelocity);
	DifferenceVector = SubtractVectors(NextRocketPosition, InterceptorPosition);
	DifferenceVectorSize = VectorSize(DifferenceVector);
	NewVelocity = MultiplyVectorWithDouble(DifferenceVector, InterceptorSpeed/DifferenceVectorSize);
	return NewVelocity;
}


// Algorithm 6
void AddErrorsToRocketsMap(TRocket *RocketsMap, int NumOfRockets, TPosition RadarPosition, double RadarAccuracy)
{
	TRocket *CurrentRocket = NULL;
	TVector PositionError;
	double PositionStdDiv, DistanceRocketRadar;
	int i;

	for (i=0 ; i < NumOfRockets ; i++)
	{
		CurrentRocket = RocketsMap + i;
		DistanceRocketRadar = VectorSize(SubtractVectors(CurrentRocket->Position, RadarPosition));
		PositionStdDiv = DistanceRocketRadar/RadarAccuracy;
		PositionError.x = PositionStdDiv*RandomGaussian(); 
		PositionError.y = PositionStdDiv*RandomGaussian();
		CurrentRocket->Position = AddVectors(PositionError, CurrentRocket->Position);
	}
}



// Algorithm 7
BOOL DecideIfLaunchRocket(
	TInitialRocketInfo *InitialRocketInfoOutPtr,
	double LaunchProbability, 
	int MinT, int MaxT, 
	double MinX, double MaxX, 
	double MinY, double MaxY, 
	double MinTheta, double MaxTheta, 
	double MinV, double MaxV
	)
{
	double Speed;
	double Theta;
	if (EventOccured(LaunchProbability))
	{
		InitialRocketInfoOutPtr->InitialPosition.x = MinX+RandomUniform()*(MaxX-MinX);
		// printf("MinX=%.3g, MaxX=%.3g, X=%.3g\n", MinX, MaxX, InitialRocketInfoOutPtr->InitialPosition.x);
		InitialRocketInfoOutPtr->InitialPosition.y = MinY+RandomUniform()*(MaxY-MinY);
		// printf("MinY=%.3g, MaxY=%.3g, Y=%.3g\n", MinY, MaxY, InitialRocketInfoOutPtr->InitialPosition.y);
		Speed = MinV+RandomUniform()*(MaxV-MinV);
		Theta = MinTheta + RandomUniform()*(MaxTheta-MinTheta);
		Theta = Theta*M_PI/180;
		InitialRocketInfoOutPtr->InitialVelocity.x = Speed*cos(Theta);
		InitialRocketInfoOutPtr->InitialVelocity.y = Speed*sin(Theta);
		InitialRocketInfoOutPtr->FlightTime = RandomInteger(MinT, MaxT);
		return TRUE;
	}
	return FALSE;
}

